#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <stdbool.h>
#include "modbus.h"
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <stdint.h>
#include <arpa/inet.h>
#include "shmem.h"      // 包含共享内存组件
#include "msg_queue_peer.h" // 包含消息队列组件

// 共享内存数据结构
typedef union equipment {
   bool a;
    int b;
    double d; // 修改为double类型
} Equipment;

// 修改后的共享内存结构体定义
typedef struct shm_modbus {
    int key;
    int type; // 1=bool, 2=int, 3=double
    int addr; 
    Equipment val;
} Shm_Modbus;

// 全局变量
modbus_t *ctx;
struct shm_param shm_para; // 使用共享内存组件参数结构体
Shm_Modbus* shared_items = NULL;
int sensor_count = 6; // 人流量、温度 + 4个开关
volatile sig_atomic_t keep_running = 1;

// 信号处理函数
void sigint_handler(int sig) {
    keep_running = 0;
}

// 浮点数转换函数
double convert_float(uint16_t reg1, uint16_t reg2) {
    // 将两个16位寄存器组合为32位整数
    uint32_t combined = ((uint32_t)reg1 << 16) | reg2;
    
    // 将32位整数转换为浮点数
    float result;
    memcpy(&result, &combined, sizeof(float));
    
    return (double)result;
}

// 数据采集线程
void *read_data(void *arg) {
    uint16_t reg[3]; // 读取5个寄存器
    
    while (keep_running) {
        modbus_set_slave(ctx, 2);
        int rc = modbus_read_registers(ctx, 0, 3, reg);
        
        if (rc != 3) {
            usleep(100000);
            continue;
        }

        // 使用寄存器1-4计算温度值
        double temperature = convert_float(reg[1], reg[2]); 
        // 更新共享内存
        if (shared_items) {
            shared_items[0].val.b = reg[0]; // 人流量
            shared_items[4].val.d = temperature;    // 空调温度
        }
        
        usleep(500000);
    }
    return NULL;
}

// 打印线程
void *print_shared_memory(void *arg) {
    while (keep_running) {
        // 打印共享内存数据
        printf("\n===== 共享内存数据 =====\n");
        
        // 遍历所有设备
        for (int i = 0; i < sensor_count; i++) {
            printf("设备 %d ,(Key=%d): ", i, shared_items[i].key);
            
            // 根据类型打印值
            switch (shared_items[i].type) {
                case 1: // bool
                    printf("%s", shared_items[i].val.a ? "开启" : "关闭");
                    break;
                case 2: // int
                    printf("%d", shared_items[i].val.b);
                    break;
                case 3: // double
                    printf("%.1f°C", shared_items[i].val.d); // 使用%.1f格式打印double
                    break;
                default:
                    printf("未知类型");
            }
            printf("\n");
        }
        
        printf("======================\n");
        
        // 固定延迟1秒
        sleep(1);
    }
    return NULL;
}

// 消息处理线程
void *process_messages(void *arg) {
    // 定义消息结构体
    typedef struct message {
        long mtype;
        char mtext[256];
    } Message;
    
    Message msg;
    int command_count = 0;
    
    while (keep_running) {
        // 接收消息
        int rc = msg_queue_recv("modbus", &msg, sizeof(Message), 1, IPC_NOWAIT);
        if (rc < 0) {
            if (errno != ENOMSG) { // 忽略空队列错误
                perror("msg_queue_recv失败");
            }
            usleep(100000); // 100ms检查一次
            continue;
        }
        
        command_count++;
        printf("\n[指令接收] 命令#%d: %s\n", command_count, msg.mtext);
        
        // 解析命令并更新状态
        int door_state = -1;      // 门开关状态（-1表示不改变）
        int window_state = -1;    // 窗户开关状态
        int air_switch_state = -1;// 空调开关状态
        int fan_state = -1;       // 风扇开关状态
        
        // 检查门开关命令
        if (strcmp(msg.mtext, "DOOR_ON") == 0) {
            door_state = 1;
        } else if (strcmp(msg.mtext, "DOOR_OFF") == 0) {
            door_state = 0;
        }
        
        // 检查窗户开关命令
        if (strcmp(msg.mtext, "WINDOW_ON") == 0) {
            window_state = 1;
        } else if (strcmp(msg.mtext, "WINDOW_OFF") == 0) {
            window_state = 0;
        }
        
        // 检查空调开关命令
        if (strcmp(msg.mtext, "AIR_SWITCH_ON") == 0) {
            air_switch_state = 1;
        } else if (strcmp(msg.mtext, "AIR_SWITCH_OFF") == 0) {
            air_switch_state = 0;
        }
        
        // 检查风扇开关命令
        if (strcmp(msg.mtext, "FAN_ON") == 0) {
            fan_state = 1;
        } else if (strcmp(msg.mtext, "FAN_OFF") == 0) {
            fan_state = 0;
        }
        
        // 如果没有有效命令
        if (door_state == -1 && window_state == -1 && 
            air_switch_state == -1 && fan_state == -1) {
            printf("未知命令: %s\n", msg.mtext);
            continue;
        }
        
        // 更新共享内存中的开关状态
        if (shared_items) {
            if (door_state != -1) {
                shared_items[1].val.a = door_state; // 门开关 (bool)
                printf("门开关状态更新为: %s\n", door_state ? "开启" : "关闭");
            }
            if (window_state != -1) {
                shared_items[2].val.a = window_state; // 窗户开关 (bool)
                printf("窗户开关状态更新为: %s\n", window_state ? "开启" : "关闭");
            }
            if (air_switch_state != -1) {
                shared_items[3].val.a = air_switch_state; // 空调开关 (bool)
                printf("空调开关状态更新为: %s\n", air_switch_state ? "开启" : "关闭");
            }
            if (fan_state != -1) {
                shared_items[5].val.a = fan_state; // 风扇开关 (bool)
                printf("风扇开关状态更新为: %s\n", fan_state ? "开启" : "关闭");
            }
        }
        
        // 控制Modbus设备
        modbus_set_slave(ctx, 1);
        if (door_state != -1) {
            modbus_write_bit(ctx, 1, door_state); // 门控制
        }
        if (window_state != -1) {
            modbus_write_bit(ctx, 2, window_state); // 窗控制
        }
        if (air_switch_state != -1) {
            modbus_write_bit(ctx, 3, air_switch_state); // 空调开关
        }
        if (fan_state != -1) {
            modbus_write_bit(ctx, 4, fan_state); // 风扇控制
        }
        
        printf("设备控制完成。\n");
    }
    return NULL;
}

int main(int argc, char const *argv[]) {
    signal(SIGINT, sigint_handler);
    
    pthread_t data_thread, print_thread, msg_thread;
    
    // ================== 使用共享内存组件 ==================
    // 初始化共享内存
    if (shm_init(&shm_para, "modbus", 1024) != 0) {
        fprintf(stderr, "共享内存初始化失败\n");
        return 1;
    }
    
    // 获取共享内存地址
    void *shm_addr = shm_getaddr(&shm_para);
    if (shm_addr == NULL) {
        fprintf(stderr, "获取共享内存地址失败\n");
        return 1;
    }
    
    // 初始化共享内存布局
    int* count_ptr = (int*)shm_addr;
    *count_ptr = sensor_count;
    
    shared_items = (Shm_Modbus*)(count_ptr + 1);
    
    // 初始化共享内存项
    // 人流量 - int类型 (type=2)
    shared_items[0].key = 101;
    shared_items[0].type = 2; // int
    shared_items[0].addr = 40001; 
    shared_items[0].val.b = 0; // 初始化
    
    // 门开关 - bool类型 (type=1)
    shared_items[1].key = 102;
    shared_items[1].type = 1; // bool
    shared_items[1].addr = 10001; 
    shared_items[1].val.a = false; // 初始化关闭
    
    // 窗户开关 - bool类型 (type=1)
    shared_items[2].key = 103;
    shared_items[2].type = 1; // bool
    shared_items[2].addr = 10002; 
    shared_items[2].val.a= false; // 初始化关闭
    
    // 空调开关 - bool类型 (type=1)
    shared_items[3].key = 104;
    shared_items[3].type = 1; // bool
    shared_items[3].addr = 10003; 
    shared_items[3].val.a = false; // 初始化关闭
    
    // 空调温度 - double类型 (type=3)
    shared_items[4].key = 105;
    shared_items[4].type = 3; // 设置为double类型
    shared_items[4].addr = 40002; 
    shared_items[4].val.d = 0.0; // 初始化为0.0
    
    // 风扇开关 - bool类型 (type=1)
    shared_items[5].key = 106;
    shared_items[5].type = 1; // bool
    shared_items[5].addr = 10004; 
    shared_items[5].val.a = false; // 初始化关闭
    // ===================================================
    
    ctx = modbus_new_tcp("192.168.50.182", 502);
    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Modbus连接失败: %s\n", modbus_strerror(errno));
        return 1;
    }
    
    printf("Modbus连接成功! 开始创建线程...\n");
    
    // 创建数据采集线程
    pthread_create(&data_thread, NULL, read_data, NULL);
    
    // 创建共享内存打印线程
    pthread_create(&print_thread, NULL, print_shared_memory, NULL);
    
    // 创建消息处理线程
    pthread_create(&msg_thread, NULL, process_messages, NULL);
    
    printf("系统初始化完成。按Ctrl+C退出...\n");
    
    // 主线程等待退出信号
    while (keep_running) {
        pause(); // 暂停等待信号
    }

    // 安全退出处理
    pthread_cancel(data_thread);
    pthread_cancel(print_thread);
    pthread_cancel(msg_thread);
    pthread_join(data_thread, NULL);
    pthread_join(print_thread, NULL);
    pthread_join(msg_thread, NULL);
    
    if (ctx) {
        modbus_close(ctx);
        modbus_free(ctx);
    }
    
    // 清理共享内存（使用组件函数）
    if (shm_del(&shm_para) != 0) {
        fprintf(stderr, "共享内存清理失败\n");
    }
    
    return 0;
}